// // B2064 斐波那契数列
// #include<bits/stdc++.h>
// using namespace std;
// int n;
// int main(){
// 	cin>>n;
// 	for(int i=1;i<=n;i++){
// 		int a;
// 		cin>>a;
// 		int x[40];
// 		x[1]=x[2]=1;
// 		for(int i=3;i<=a;i++)
// 			x[i]=x[i-1]+x[i-2];
// 		cout<<x[a]<<endl;
// 	}
// 	return 0;
// }

// // P1024 [NOIP 2001 提高组] 一元三次方程求解
// #include <iostream>
// #include <cstdio>
// using namespace std;
// int main()
// {
//    double a,b,c,d;
//    scanf("%lf%lf%lf%lf",&a,&b,&c,&d);
//    for(double i=-100;i<=100;i+=0.001)
//    {
//       double j=i+0.001;
//       double y1=a*i*i*i+b*i*i+c*i+d;
//       double y2=a*j*j*j+b*j*j+c*j+d;
//       if(y1>=0&&y2<=0||y1<=0&&y2>=0)
//       {
//          double x=(i+j)/2;
//          printf("%.2lf ",x);
//       }
//    }
// }

// P2516 [HAOI2010] 最长公共子序列
// #include<iostream>
// #include<cstdio>
// #include<cstring>
// #include<cmath>
// #include<cstdlib>
// #include<algorithm> 
// #define mod 100000000
// #define ll long long
// #define re register 
// using namespace std;
// int f[2][5005]={},r[2][5005]={};//必须开滚动数组，不开绝对爆空间,由于动态规划中，一个阶段的决策只受上一个阶段的影响，
// //因此可以将以前的状态覆盖掉。只要存两个状态，故只开第一个下标为0~1的二维数组  
// //r[i][j]存第一个字串前i个（一直被轮换），第二个字串前j个最长子序列的个数 
// char s1[5005]={},s2[5005]={};
// int n,m;
// int main()
// {    
//     scanf("%s",s1+1);//s1+1代表从s1[1]开始读入数据，s[0]不读入 
//     n=strlen(s1+1)-1;
//     scanf("%s",s2+1);
//     m=strlen(s2+1)-1;
//     re int now=1,pre=0;//这两个变量用来判断两个状态中哪个是以前状态（pre），哪个是现在状态（now）（滚动数组的产物） 
//     for(re int k=0;k<=m;k++)
//       r[0][k]=1;//初始化，长度为0最长子序列方案数为1（第一个序列长度为0） 
//     r[1][0]=1;//长度为0最长子序列方案数为1（第二个序列长度为0） 
//     for(re int i=1;i<=n;i++)
//     {
//         for(re int j=1;j<=m;j++)
//         {
//             f[now][j]=max(f[pre][j],f[now][j-1]);
//             r[now][j]=0;//后面的方案数都是由前面加过来的, 本质上是会受到之前的设置的数字的影响
//             if(s1[i]==s2[j])f[now][j]=max(f[now][j],f[pre][j-1]+1); 
//             if(s1[i]==s2[j]&&f[now][j]==f[pre][j-1]+1) r[now][j]+=r[pre][j-1];
//             if(f[pre][j]==f[now][j]) r[now][j]+=r[pre][j];
//             if(f[now][j-1]==f[now][j]) r[now][j]+=r[now][j-1];//加上f[i-1][j]和f[i][j-1]中=k的方案数
//             if(f[pre][j-1]==f[now][j]) r[now][j]-=r[pre][j-1];//如果a[i]!=b[j]且f[i-1][j-1]=k，就要减去它的方案数
//             r[now][j]=(r[now][j]+mod)%mod;//+mod可以省略 
//         }
//         now=pre;pre=1-pre;//滚动    
//     }
//     printf("%d\n%d",f[pre][m],r[pre][m]);
//     return 0;
// }

// // P1880 [NOI1995] 石子合并
// #include <cstdio>
// #include <cstring>
// int n;
// int a[200];
// int f[200][200] = {0}; //不用初始化边界了
// int fx[200][200] = {0}; //不用初始化边界了,存最小值
// int pre[200] = {0};
// int ans_max = -1;
// int ans_min = 0x7f7f7f7f;
// int max(int a,int b){
//     if( a >b ) return a;
//     return b;
// }
// int min(int a,int b){
//     if( a <b ) return a;
//     return b;
// }
// int sum(int i,int j){
//     return pre[j] - pre[i-1];
// }
// int main(){
//     int i,j,k;
//     scanf("%d",&n);
//     for(i=1;i<=n;i++){
//         scanf("%d",&a[i]);
//         a[n+i] = a[i];
//     }
//     int len = (n<<1)-1;
//     for(i=1;i<=len;i++){
//         pre[i] = pre[i-1] +a[i];
//     }
//     memset(fx,0x7f,sizeof(fx));
//     for(i=0;i<=200;i++) fx[i][i] = 0;
//     for(i=2;i<=n;i++){ // 合并几堆石子
//         for(j=1;j<=len-i+1;j++){
//             for(k=j;k<j+i-1;k++){
//              int m =  f[j][k] + f[k+1][j+i-1];
//              int xiao = fx[j][k] +fx[k+1][j+i-1];
//              if( f[j][j+i-1] < m) //求 max
//                  f[j][j+i-1] = m;
//              if( fx[j][j+i-1] > xiao) //求 max
//                  fx[j][j+i-1] = xiao;
//             }
//             f[j][j+i-1] += sum(j,j+i-1);
//             fx[j][j+i-1] += sum(j,j+i-1);
//         }
//     }
//     for(i=1;i<=n;i++){
//         if( ans_max < f[i][i+n-1])
//             ans_max = f[i][i+n-1];
//         if( ans_min > fx[i][i+n-1])
//             ans_min = fx[i][i+n-1];
//     }
//     printf("%d\n",ans_min);
//     printf("%d",ans_max);
//     return 0;
// }

// B2034 计算 2 的幂
// #include<bits/stdc++.h>//万能头
// using namespace std;
// int pow_2(int x){
// 	int ans=2;
//    if(x==0) return 1;//这里需要特判一下2^0
// 	for(int i=2;i<=x;i++)
// 		ans*=2;
// 	return ans;
// }
// int main(){
// 	int n;
// 	scanf("%d",&n);
// 	printf("%d",pow_2(n));
// 	return 0;//好习惯*1
// }

// P1049 [NOIP 2001 普及组] 装箱问题
// #include <bits/stdc++.h>
// #define V 20010
// #define maxn 35
// using namespace std;

// int n, m;
// int f[maxn][V], a[maxn];
// int main() {
// 	cin >> m >> n;
// 	for (int i = 1; i <= n; i++)
// 		cin >> a[i];
// 	for (int i = 1; i <= n; i++)
// 		f[i][0] = 0; //初始化 
// 	for (int i = 1; i <= n; i++)
// 		for (int j = 1; j <= m; j++)
// 			if(j >= a[i]) f[i][j] = max(f[i - 1][j], f[i - 1][j - a[i]] + a[i]); //找到最大体积
// 			else f[i][j] = f[i - 1][j]; //如果背包容量转不下就复制前面的
// 	cout << m - f[n][m] << endl; //最后剩余的空间：原有的背包熔炼-最终可以装下的最多体积
//     return 0;
// }

// P1048 [NOIP 2005 普及组] 采药
// #include "iostream"
// #include "stdio.h"
// using namespace std;
// int w[105],val[105];
// int dp[105][1005];
// int main()
// {
//     int t,m,res=-1;
//     scanf("%d%d",&t,&m);
//     for(int i=1;i<=m;i++)
//     {
//         scanf("%d%d",&w[i],&val[i]);
//     }
//     for(int i=1;i<=m;i++) 
//         for(int j=t;j>=0;j--)  
//         {
//             if(j>=w[i])
//             {
//                 dp[i][j]=max(dp[i-1][j-w[i]]+val[i],dp[i-1][j]);
//             }  
//             else
//             {
//                 dp[i][j]=dp[i-1][j];
//             }              
//         }
//     printf("%d",dp[m][t]);
//     return 0;
// }

// P1060 [NOIP 2006 普及组] 开心的金明
// #include<iostream>
// #include<algorithm>
// using namespace std;
// int w[30],v[30],f[50000];//w数组为重要度，v数组为money，f是用来dp的数组
// int n,m;//n是总物品个数，m是总钱数
// int main()
// {
//     cin>>m>>n;//输入
//     for(int i=1;i<=n;i++)
//     {
//         cin>>v[i]>>w[i];
//         w[i]*=v[i];//w数组在这里意义变为总收获（重要度*money）
//     }
//        //01背包（参照第二类模板“一维数组优化”）
//     for(int i=1;i<=n;i++)
//     {
//         for(int j=m;j>=v[i];j--)//注意从m开始
//         {
//             // if(j>=v[i])
//             {
//                 f[j]=max(f[j],f[j-v[i]]+w[i]);//dp
//             // }
//         }
//     }
//     cout<<f[m]<<endl;//背包大小为m时最大值
//     return 0;
// } 

// // P1063 [NOIP 2006 提高组] 能量项链
// #include <bits/stdc++.h>
// using namespace std;
// int f[405][405];
// int n,a[205]; 
// int main()
// {
//     cin >> n;
//     for(int i=1;i<=n;i++)  //***对环形问题的处理技巧***
//     {
//         cin >> a[i];
//         a[n+i]=a[i];
//     } 
//     for(int i=2;i<=n+1;i++)
//     {
//         for(int l=1;l+i-1<=2*n;l++)  //如果采取了上述策略，一定要将2*n个点都更新 
//         {
//             int r=l+i-1;
//             for(int k=l+1;k<=l+i-2;k++)
//                 f[l][r]=max(f[l][r],f[l][k]+f[k][r]+a[l]*a[k]*a[r]); 
//         }
//     }kkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkk
//     int res=0;
//     for (int i=1;i<=n;i++) res=max(res,f[i][n+i]);
//     cout << res;
//     return 0;
// }

// // P1208 [USACO1.3] 混合牛奶 Mixing Milk
// #include<bits/stdc++.h>
// using namespace std;
// int n,m;//n需要牛奶的总数,m提供牛奶的农民个数
// int tot=0;//tot记录花的钱
// struct node
// {
//     int a,p;
// } a[100010];
// int cmp(node x,node y)//结构体比较
// {
//     return x.p<y.p;
// }
// int main()
// {
//     cin>>n>>m;
//     for(int i=1; i<=m; i++)
//         cin>>a[i].p>>a[i].a;
//     sort(a+1,a+m+1,cmp);//sort快排
//     for(int i=1; i<=m; i++)
//         if(n>0)
//         {
//             if(n>a[i].a)
//             {
//                 n-=a[i].a;
//                 tot+=a[i].p*a[i].a;
//             }
//             else if(n<=a[i].a)//因为最后一个农夫的奶用不完
//             {
//                 tot+=a[i].p*n;//看还需多少奶，这里记录钱必须在n--前，要不然就成负数了
//                 n-=a[i].a;
//             }
//         }
//     cout<<tot;
// }

// // P1650 田忌赛马
// #include<stdio.h>
// #include<algorithm>
// using namespace std;
// int n;int qw[2000];int tj[2000];
// int* headqw;int* tailqw;int* headtj;int* tailtj;
// int res;
// int main()
// {
//     scanf("%d",&n);
//     for(int i=0;i<n;i++)
//     {
//         scanf("%d",&tj[i]);
//     }
//     for(int i=0;i<n;i++)
//     {
//         scanf("%d",&qw[i]);
//     }
//     sort(tj,tj+n);sort(qw,qw+n);//排序
//     tailqw=qw;tailtj=tj;headqw=qw+n-1;headtj=tj+n-1;//头尾指针，方便代码
//     for(int i=0;i<n;i++)
//     {
//         if(*headtj>*headqw)//头是否能赢
//         {
//             res+=200;headtj--;headqw--;
//             continue;
//         }
//         if(*tailtj>*tailqw)//尾是否能赢
//         {
//             res+=200;tailtj++;tailqw++;
//             continue;
//         }
//         if(*tailtj<*headqw)//硬怼
//         {
//             res-=200;
//             tailtj++;headqw--;
//         }
//         else if(*tailtj==*headqw)//特判！！！（敲黑板）不加就是10分！
//         {
//             tailtj++;headqw--;
//         }
//     }
//     printf("%d",res);
//     return 0;//拜拜程序~
// }

// // P1181 数列分段 Section I
// #include<bits/stdc++.h>
// using namespace std;
// int n,m;
// int main(){
//     scanf("%d%d",&n,&m);
//     int sum=0;
//     int p;
//     int num=0;
//     for(int i = 0; i < n; i++){
//         scanf("%d",&p);
//         int c=p+num;
//         if(c>m){sum++;num=p;}
//         else num=c;
//     }
//     printf("%d",sum+1);
//     return 0;
// }

// // P1094 [NOIP 2007 普及组] 纪念品分组
// #include<bits/stdc++.h>
// using namespace std;
// int w,n,i,j,sum;
// int p[30004];
// int main(){
// 	scanf("%d%d",&w,&n);
// 	i=1,j=n;
// 	for(int i=1;i<=n;i++)scanf("%d",&p[i]);
// 	sort(p+1,p+1+n);
// 	while(i<=j){
// 		if(p[j]>w||p[i]>w||(p[i]+p[j])>w){
// 			sum++;
// 			j--;
// 			continue;
// 		}
// 		sum++;
// 		i++;
// 		j--;
// 	}
// 	printf("%d",sum);
// 	return 0;
// }

// // P1090 [NOIP 2004 提高组] 合并果子
// #include <bits/stdc++.h>
// using namespace std;

// int n, m, ans;
// priority_queue<int, vector<int>, greater<int> > q;
// int main() {
//     cin >> m;
//     for (int i = 1; i <= m; i++) {
//         int t;
//         cin >> t;
//         q.push(t);
//     }
//     while (q.size() > 1) { // 合并完了之后的结果
//         int t1 = q.top(); q.pop();
//         int t2 = q.top(); q.pop();
//         ans += t1 + t2;
//         q.push(t1 + t2);
//     }
//     cout << ans << endl;
//     return 0;
// }

// // P1036 [NOIP 2002 普及组] 选数
// #include <iostream>
// using namespace std;
// int n, m;
// int a[25];
// long long ans;
// bool prime(int x){      //判断素数不必多说
//     if(x == 1 || x != 2 && x % 2 == 0) return 0;
//     for(int i = 3; i * i <= x; i++) if(x % i == 0) return 0;
//     return 1;
// }
// void DFS(int k, int s, int x){      //k表示当前已选的数的个数，s表示这几个数的和，x表示上一个选择的数的下一位
//     if(k == m){
//         if(prime(s)) ans++;
//         return;
//     }
//     for(int i = x; i < n; i++) DFS(k + 1, s + a[i], i + 1);      //从x开始选，保证是升序
// }
// int main(){
//     cin >> n >> m;
//     for(int i = 0; i < n; i++) cin >> a[i];
//     DFS(0, 0, 0);
//     cout << ans << "\n";
//     return 0;
// }

// // P1706 全排列问题
// #include<iostream>//P1706
// #include<cstdio>
// #include<cstring>
// #include<string>
// #include<iomanip>
// #include <algorithm>
// #include<cmath>
// #include<vector>
// #include<set>
// using namespace std;
// int a[10];
// int main()
// {
// 	int n,i,j=1,k;
// 	cin>>n;
// 	for(i=1;i<=n;i++)
// 	 {a[i]=n-i+1;j*=i;}//题目好像没说要从小到大输出
//      //但保险起见还是初始赋值为最大序列
//      //即a[1~n]=n~1;顺便计算n!
// 	for(i=1;i<=j;i++)
// 	 {next_permutation(a+1,a+n+1);
// 	  for(k=1;k<=n;k++)
// 	   cout<<"    "<<a[k];//排一次输出一次
//        //空格建议复制
// 	  cout<<endl;
// 	 }
// 	 return 0;
// }












// #include <iostream>
// #include <algorithm>
// #include <vector>
// using namespace std;
// vector<int> a;
// int main() {
//     int w, n;
//     cin >> w >> n;
//     for(int i = 0; i < n; i++) {
//         int temp;
//         cin >> temp;
//         a.push_back(temp);
//     }
//     sort(a.begin(), a.end());
//     int l = 0, r = n - 1;
//     int cnt = 0;
//     while(l <= r) {
//         if(a[l] > w || a[r] > w || a[l] + a[r] > w) {
//             r--;
//             cnt++;
//             continue;
//         }
//         cnt++;
//         r--;
//         l++;
//     }
//     cout << cnt << endl;
//     return 0;
// }









// #include <iostream>
// #include <vector>
// using namespace std;
// vector<int> a;
// int ret = 0;
// int n, k;
// bool isPrime(int x) {
//     if(x == 1 || (x % 2 == 0 && x != 2)) {
//         return false;
//     }
//     for(int i = 3; i * i <= x; i++) {
//         if(x % i == 0) {
//             return false;
//         }
//     }
//     return true;
// }
// void dfs(int index, int sum, int target) {
//     if(k == target) {
//         if(isPrime(sum)) {
//             ret++;
//         }
//         return;
//     }
//     for(int i = index; i < n; i++) {
//         dfs(i + 1, sum + a[i], target + 1);
//     }
// }
// int main() {
//     cin >> n >> k;
//     for(int i = 0; i < n; i++) {
//         int temp;
//         cin >> temp;
//         a.push_back(temp);
//     }
//     dfs(0, 0, 0);
//     cout << ret << endl;
//     return 0;
// }




































// #include <iostream>
// using namespace std;
// char a[5010], b[5010];
// int f[2][5010], r[2][5010];
// #define mod 100000000
// int main() {
//     string s1, s2;
//     cin >> s1 >> s2;
//     int n = s1.size() - 1, m = s2.size() - 1;
//     for(int i = 0; i < s1.size() - 1; i++) {
//         a[i + 1] = s1[i];
//     }
//     for(int i = 0; i < s2.size() - 1; i++) {
//         b[i + 1] = s2[i];
//     }
//     for(int i = 0; i <= m; i++) {
//         r[0][i] = 1;
//     }
//     r[1][0] = 1;
//     int now = 1, pre = 0;
//     for(int i = 1; i <= n; i++) {
//         for(int j = 1; j <= m; j++) {
//             f[now][j] = max(f[pre][j], f[now][j - 1]);
//             r[now][j] = 0;
//             if(a[i] == b[j]) f[now][j] = max(f[pre][j], f[pre][j - 1] + 1);
//             if(a[i] ==  b[j] && f[now][j] == f[pre][j - 1] + 1) r[now][j] += r[pre][j - 1];
//             if(f[pre][j] == f[now][j]) r[now][j] += r[pre][j];
//             if(f[now][j - 1] == f[now][j]) r[now][j] += r[now][j - 1];
//             if(f[pre][j - 1] == f[now][j]) r[now][j] -= r[pre][j - 1];
//             r[now][j] = (r[now][j] + mod) % mod;
//         }
//         now = pre;
//         pre = 1 - pre;
//     }
//     cout << f[pre][m] << endl << r[pre][m] << endl;
//     return 0;
// }



#include <iostream>
#include <algorithm>
#include <vector>
using namespace std;
vector<int> a;
int main() {
    int n; 
    cin >> n;
    int m = 1;
    for(int i = 1; i <= n; i++) {
        m *= i;
        a.push_back(n - i + 1);
    }
    for(int j = 0; j < m; j++) {
        next_permutation(a.begin(), a.end());
        for(auto& e : a) {
            cout << "    " << e;
        }
        cout << endl;
    }
    return 0;
}